home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / NEW_TECH / AWKSRC.ZIP / EVAL.C < prev    next >
C/C++ Source or Header  |  1993-09-27  |  32KB  |  1,223 lines

  1. /*
  2.  * eval.c - gawk parse tree interpreter 
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1986, 1988, 1989, 1991, 1992 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming Language.
  10.  * 
  11.  * GAWK is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  * 
  16.  * GAWK is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GAWK; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "awk.h"
  27.  
  28. extern double pow P((double x, double y));
  29. extern double modf P((double x, double *yp));
  30. extern double fmod P((double x, double y));
  31.  
  32. static int eval_condition P((NODE *tree));
  33. static NODE *op_assign P((NODE *tree));
  34. static NODE *func_call P((NODE *name, NODE *arg_list));
  35. static NODE *match_op P((NODE *tree));
  36.  
  37. NODE *_t;        /* used as a temporary in macros */
  38. #ifdef MSDOS
  39. double _msc51bug;    /* to get around a bug in MSC 5.1 */
  40. #endif
  41. NODE *ret_node;
  42. int OFSlen;
  43. int ORSlen;
  44. int OFMTidx;
  45. int CONVFMTidx;
  46.  
  47. /* Macros and variables to save and restore function and loop bindings */
  48. /*
  49.  * the val variable allows return/continue/break-out-of-context to be
  50.  * caught and diagnosed
  51.  */
  52. #define PUSH_BINDING(stack, x, val) (memcpy ((char *)(stack), (char *)(x), sizeof (jmp_buf)), val++)
  53. #define RESTORE_BINDING(stack, x, val) (memcpy ((char *)(x), (char *)(stack), sizeof (jmp_buf)), val--)
  54.  
  55. static jmp_buf loop_tag;    /* always the current binding */
  56. static int loop_tag_valid = 0;    /* nonzero when loop_tag valid */
  57. static int func_tag_valid = 0;
  58. static jmp_buf func_tag;
  59. extern int exiting, exit_val;
  60.  
  61. /*
  62.  * This table is used by the regexp routines to do case independant
  63.  * matching. Basically, every ascii character maps to itself, except
  64.  * uppercase letters map to lower case ones. This table has 256
  65.  * entries, which may be overkill. Note also that if the system this
  66.  * is compiled on doesn't use 7-bit ascii, casetable[] should not be
  67.  * defined to the linker, so gawk should not load.
  68.  *
  69.  * Do NOT make this array static, it is used in several spots, not
  70.  * just in this file.
  71.  */
  72. #if 'a' == 97    /* it's ascii */
  73. char casetable[] = {
  74.     '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
  75.     '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
  76.     '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
  77.     '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
  78.     /* ' '     '!'     '"'     '#'     '$'     '%'     '&'     ''' */
  79.     '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
  80.     /* '('     ')'     '*'     '+'     ','     '-'     '.'     '/' */
  81.     '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
  82.     /* '0'     '1'     '2'     '3'     '4'     '5'     '6'     '7' */
  83.     '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
  84.     /* '8'     '9'     ':'     ';'     '<'     '='     '>'     '?' */
  85.     '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
  86.     /* '@'     'A'     'B'     'C'     'D'     'E'     'F'     'G' */
  87.     '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  88.     /* 'H'     'I'     'J'     'K'     'L'     'M'     'N'     'O' */
  89.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  90.     /* 'P'     'Q'     'R'     'S'     'T'     'U'     'V'     'W' */
  91.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  92.     /* 'X'     'Y'     'Z'     '['     '\'     ']'     '^'     '_' */
  93.     '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
  94.     /* '`'     'a'     'b'     'c'     'd'     'e'     'f'     'g' */
  95.     '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  96.     /* 'h'     'i'     'j'     'k'     'l'     'm'     'n'     'o' */
  97.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  98.     /* 'p'     'q'     'r'     's'     't'     'u'     'v'     'w' */
  99.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  100.     /* 'x'     'y'     'z'     '{'     '|'     '}'     '~' */
  101.     '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
  102.     '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  103.     '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  104.     '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  105.     '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  106.     '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  107.     '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  108.     '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  109.     '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  110.     '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
  111.     '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
  112.     '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
  113.     '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
  114.     '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  115.     '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  116.     '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  117.     '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  118. };
  119. #else
  120. #include "You lose. You will need a translation table for your character set."
  121. #endif
  122.  
  123. /*
  124.  * Tree is a bunch of rules to run. Returns zero if it hit an exit()
  125.  * statement 
  126.  */
  127. int
  128. interpret(tree)
  129. register NODE *volatile tree;
  130. {
  131.     jmp_buf volatile loop_tag_stack; /* shallow binding stack for loop_tag */
  132.     static jmp_buf rule_tag; /* tag the rule currently being run, for NEXT
  133.                   * and EXIT statements.  It is static because
  134.                   * there are no nested rules */
  135.     register NODE *volatile t = NULL;    /* temporary */
  136.     NODE **volatile lhs;    /* lhs == Left Hand Side for assigns, etc */
  137.     NODE *volatile stable_tree;
  138.     int volatile traverse = 1;    /* True => loop thru tree (Node_rule_list) */
  139.  
  140.     if (tree == NULL)
  141.         return 1;
  142.     sourceline = tree->source_line;
  143.     source = tree->source_file;
  144.     switch (tree->type) {
  145.     case Node_rule_node:
  146.         traverse = 0;   /* False => one for-loop iteration only */
  147.         /* FALL THROUGH */
  148.     case Node_rule_list:
  149.         for (t = tree; t != NULL; t = t->rnode) {
  150.             if (traverse)
  151.                 tree = t->lnode;
  152.             sourceline = tree->source_line;
  153.             source = tree->source_file;
  154.             switch (setjmp(rule_tag)) {
  155.             case 0:    /* normal non-jump */
  156.                 /* test pattern, if any */
  157.                 if (tree->lnode == NULL ||
  158.                     eval_condition(tree->lnode))
  159.                     (void) interpret(tree->rnode);
  160.                 break;
  161.             case TAG_CONTINUE:    /* NEXT statement */
  162.                 return 1;
  163.             case TAG_BREAK:
  164.                 return 0;
  165.             default:
  166.                 cant_happen();
  167.             }
  168.             if (!traverse)          /* case Node_rule_node */
  169.                 break;          /* don't loop */
  170.         }
  171.         break;
  172.  
  173.     case Node_statement_list:
  174.         for (t = tree; t != NULL; t = t->rnode)
  175.             (void) interpret(t->lnode);
  176.         break;
  177.  
  178.     case Node_K_if:
  179.         if (eval_condition(tree->lnode)) {
  180.             (void) interpret(tree->rnode->lnode);
  181.         } else {
  182.             (void) interpret(tree->rnode->rnode);
  183.         }
  184.         break;
  185.  
  186.     case Node_K_while:
  187.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  188.  
  189.         stable_tree = tree;
  190.         while (eval_condition(stable_tree->lnode)) {
  191.             switch (setjmp(loop_tag)) {
  192.             case 0:    /* normal non-jump */
  193.                 (void) interpret(stable_tree->rnode);
  194.                 break;
  195.             case TAG_CONTINUE:    /* continue statement */
  196.                 break;
  197.             case TAG_BREAK:    /* break statement */
  198.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  199.                 return 1;
  200.             default:
  201.                 cant_happen();
  202.             }
  203.         }
  204.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  205.         break;
  206.  
  207.     case Node_K_do:
  208.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  209.         stable_tree = tree;
  210.         do {
  211.             switch (setjmp(loop_tag)) {
  212.             case 0:    /* normal non-jump */
  213.